/**
 * File comment: Prototype client session abstract, different 
 * sessions will be given based on rank in the system.
 */
package edu.gatech.oad.project.networking;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import edu.gatech.oad.project.networking.messages.Message;
import edu.gatech.oad.project.networking.messages.clientMessages.getAllDoctorMessage;
import edu.gatech.oad.project.operations.data.Appointment;
import edu.gatech.oad.project.operations.data.PatientInformation;
import edu.gatech.oad.project.operations.users.Doctor;
import edu.gatech.oad.project.operations.users.User;
import edu.gatech.oad.project.presentation.DriverMain;

/**
 * Abstract Client Session to be extended by
 * specific client sessions
 * 
 * @author James Moore
 * @version 1.0
 */
public abstract class ClientSession {
    
    /**
     * Field socket: socket of the server
     */
    protected Socket server;
    
    /**
     * Field outBound: out stream for server
     */
    protected ObjectOutputStream outBound;
    
    /**
     * Field inBound: in stream for server
     */
    protected ObjectInputStream inBound;
    
    /**
     * Field token: the security token
     */
    protected long token;
    
    /**
     * Field user: the user logged in
     */
    protected User user;
    
    /**
     * Field myLogger: holds the logget for the clients file
     */
    protected static final Logger MYLOGGER = Logger.getLogger("edu.gatech." +
            "oad.project.presentation");
    
    /**
     * Default client session constructer
     * 
     * @param server socket
     * @param outBound stream to the server
     * @param inBound stream to the server
     * @param token security token generated by server
     * @param user current user logged in
     */
    public ClientSession(Socket server, ObjectOutputStream outBound, 
                            ObjectInputStream inBound, long token, User user) {
        this.server = server;
       
        this.outBound = outBound;
        this.inBound = inBound;
        this.token = token;
        System.out.println(token);
        System.out.flush();
            
        this.user = user;
        
        MYLOGGER.addHandler(DriverMain.FILEHANDLER);
        MYLOGGER.setLevel(Level.ALL);

    }
    /**
    private Doctor findDoctor(String docName) {
        
        return new Doctor("temp", 1);
    }*/
    /**
     * Gets the patients information based on there name
     * 
     * @param name of the patient
     * @return patient info
     */
    public abstract PatientInformation getPatientInfo(String name);
    
    /**
     * Updates the patients info based on their name
     * 
     * @param name of the patient
     * @param info updated information of the patient
     */
    public abstract void updatePatientInfo(String name, PatientInformation info);
    
    /**
     * Gets all the appointments for a patient
     * 
     * @return the appointments of a patient
     */
    public abstract List<Appointment> getAppointmentByPatient();

    /**
     * Returns the logged in user
     * 
     * @return the user
     */
    public User getUser() {
        return user;
    }

    /**
     * Requests the server for all the doctors names
     * 
     * @return the doctors names
     */
    public String[] getAllDoctors() {
        String[] doctors = new String[] {"Doctors Unavailable At This Time"};
        final Message response = this.sendMessage(new getAllDoctorMessage(token));
        if (response.getToken() == token){
            if(response.getData() != null) {
                final Doctor[] docs = (Doctor[]) response.getData();
                if (docs.length >= 1){
                    doctors = new String[docs.length];
                    for(int i = 0; i < doctors.length; i++){
                        if (docs[i] != null) {
                            doctors[i] = docs[i].getName();
                        }
                        else {
                            doctors[i] = "Doctor Not Available";
                        }
                        
                    }
                }
            }
        }
        return doctors;
    }
    
    /**
     * Sends a message across the network
     * 
     * @param mess the message to send
     * @return the response from the network
     */
    public Message sendMessage(Message mess) {
        try {
            this.outBound.writeUnshared(mess);
            this.outBound.flush();
            final Message response = (Message) this.inBound.readUnshared();
            return response;
        } catch (IOException e) {
            MYLOGGER.severe("" + e);
        } catch (ClassNotFoundException e) {
            MYLOGGER.severe("" + e);
        }
        return null;
    }
}
